home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 476-500 / disk_500 / wiconify / wiconify-source.lzh / Source / wMain.c < prev    next >
C/C++ Source or Header  |  1991-04-19  |  14KB  |  442 lines

  1. /*
  2.  *  WICONIFY    A utility that allows you to iconify any Intuition window
  3.  *              on any screen, and to open WB windows on any screen.
  4.  *
  5.  *  wMain.c     The handler setup and main loop routines
  6.  *
  7.  *  Copyright 1990 by Davide P. Cervone, all rights reserved.
  8.  *  You may use this code, provided this copyright notice is kept intact.
  9.  */
  10.  
  11. #define INTUITION_PREFERENCES_H             /* don't need 'em */
  12. #include <intuition/intuitionbase.h>
  13. #include "wHandler.h"
  14. #include "wSetup.h"
  15. #include "wMenu.h"
  16. #include <exec/interrupts.h>
  17. #include <devices/input.h>
  18. #include <libraries/dos.h>
  19.  
  20. static int MessageCount;       /* number of messages still not returned */
  21.  
  22. extern void wHandlerStub();
  23. static struct Interrupt wIconInterrupt = /* the Interrupt needed to add a */
  24. {                                         /*  handler to the input chain */
  25.    {NULL, NULL, 0, 51, NULL},             /*  ln_Pri = 51 (before Intuition) */
  26.    NULL,
  27.    &wHandlerStub                         /* the handler to add */
  28. };
  29.  
  30.  
  31. extern struct wMenuItem OpenWindowMenu[];
  32. extern void cOpenScreen(),FreeAllLists();
  33.  
  34. extern void aOpenWindow(),aCloseWindow();
  35. extern void aOpenScreen(),aCloseScreen();
  36. extern void aSetWindowTitles(),aWindowToFront(),aWindowToBack();
  37. extern void aActivateWindow();
  38. extern void aBuildSysRequest(),aFreeSysRequest(),aAutoRequest();
  39.  
  40. /*
  41.  *  Storage for the old library vectors that are replaced by SetFunction
  42.  */
  43. long OldOpenWindow,OldCloseWindow,OldOpenScreen,OldCloseScreen;
  44. long OldSetWindowTitles,OldWindowToFront,OldWindowToBack;
  45. long OldActivateWindow,OldBuildSysRequest,OldFreeSysRequest,OldAutoRequest;
  46.  
  47. /*
  48.  *  The data needed by the loader to set up the handler
  49.  */
  50. static struct HandlerData HandlerData =
  51. {
  52.    MAJVERSION,MINVERSION,
  53.    NULL, NULL,
  54.    &IntuitionBase, &GfxBase, &LayersBase, &SysBase, &DOSBase,
  55.    &wIconInterrupt,
  56.    &wMenu[0],&OpenWindowMenu[0],
  57.    &DefaultIcon, &DefaultScreenIcon,
  58.    &HiResCLICommand, &LoResCLICommand, &StackSize,
  59.    &DefaultImage, &DefaultSelect, &DefaultMask,
  60.    &DefaultScreenImage, &DefaultScreenSelect, &DefaultScreenMask,
  61.    &DefaultFlags,
  62.    &DefaultScreenFlags,
  63.    &IgnoreScreen,
  64.    &IconifyKey,&ActivateKey,
  65.    &IconifyQuals,&IconifyDisquals,&IconifyChange,
  66.    &ActivateQuals,
  67.    &Colors[0],
  68.    &cOpenScreen,&FreeAllLists,
  69.    &aOpenWindow,&OldOpenWindow,
  70.    &aCloseWindow,&OldCloseWindow,
  71.    &aOpenScreen,&OldOpenScreen,
  72.    &aCloseScreen,&OldCloseScreen,
  73.    &aSetWindowTitles,&OldSetWindowTitles,
  74.    &aWindowToFront,&OldWindowToFront,
  75.    &aWindowToBack,&OldWindowToBack,
  76.    &aActivateWindow,&OldActivateWindow,
  77.    &aBuildSysRequest,&OldBuildSysRequest,
  78.    &aFreeSysRequest,&OldFreeSysRequest,
  79.    &aAutoRequest,&OldAutoRequest
  80. };
  81.  
  82.  
  83. extern struct MsgPort *CreatePort();
  84. extern void DeletePort();
  85. extern void wMain();
  86. extern void ReplyMessages();
  87.  
  88.  
  89. /*
  90.  *  Setup()
  91.  *
  92.  *  This routine MUST be linked into the handler as the first routine.
  93.  *  It is called by the loader to check version numbers, and to get
  94.  *  the handler data structure.  It should compare the version number
  95.  *  and return NULL if a mismatch occurs or a pointer to HandlerData
  96.  *  if all is OK.
  97.  *  
  98.  *  Since the handler is started as a process, it will also be called
  99.  *  as the process first starts up.  FirstCall is used to tell which
  100.  *  invocation this is.
  101.  *  
  102.  *  When it is called as part of the process starting up
  103.  *    Get our task pointer for use by the handler routines
  104.  *    Create a port for icon messages
  105.  *    And one for the window's common UserPort
  106.  *    Get a signal for when the last window on a screen is closed
  107.  *    If all of these were allocated
  108.  *      Clear the close signal
  109.  *      If the Real WB is open and we have a backdrop window on it
  110.  *        Set and clear the menu strip (to get the NL-Deamon to change
  111.  *          its pen number, in case it is going to)
  112.  *        Signal the loader that all is OK so far
  113.  *        Wait for the loader to finish setting up
  114.  *        If we were not cancelled, call the main loop routine
  115.  *        Get ready to singal OK
  116.  *      Otherwise (something could not be set up) Get ready to signal CANCEL
  117.  *    Reply to any messages in the UserPort or IconPort
  118.  *    Free the ports that were allocated
  119.  *    Signal the loader (either OK or CANCEL)
  120.  */
  121.  
  122. struct HandlerData *Setup(MajLoadVers,MinLoadVers)
  123. int MajLoadVers,MinLoadVers;
  124. {
  125.    ULONG theSignal;
  126.    static int FirstCall = TRUE;
  127.    struct HandlerData *theData = &HandlerData;
  128.    
  129.    if (FirstCall)
  130.    {
  131.       if (MajLoadVers < MAJLOADVERS ||
  132.          (MajLoadVers == MAJLOADVERS && MinLoadVers < MINLOADVERS))
  133.             theData = NULL;
  134.       FirstCall = FALSE;
  135.    } else {
  136.       theData = NULL;
  137.       IconTask  = FindTask(NULL);
  138.       wIconPort = CreatePort(WICONPORT);
  139.       wUserPort = CreatePort(NULL);
  140.       CloseSigBit = AllocSignal(-ONE);
  141.       if (wIconPort && wUserPort && CloseSigBit != -ONE)
  142.       {
  143.          CloseSignal = (ONE << CloseSigBit);
  144.          SetSignal(CloseSignal,0L);
  145.          if (RealWB && RealWB->BackDrop)
  146.          {
  147.             SetMenuStrip(RealWB->BackDrop,wMenu); /* for NL-Deamon */
  148.             ClearMenuStrip(RealWB->BackDrop);
  149.          }
  150.          Signal(HandlerData.ParentTask,OKSIGNAL);
  151.          theSignal = Wait(OKSIGNAL| CANCELSIGNAL);
  152.          if ((theSignal & CANCELSIGNAL) == FALSE) wMain();
  153.          theSignal = OKSIGNAL;
  154.       } else theSignal = CANCELSIGNAL;
  155.       Forbid();
  156.       ReplyMessages();
  157.       if (wIconPort) DeletePort(wIconPort);
  158.       if (wUserPort) DeletePort(wUserPort);
  159.       Signal(HandlerData.ParentTask,theSignal);
  160.    }
  161.    return(theData);
  162. }
  163.  
  164.  
  165. /*
  166.  *  CreatePort()
  167.  *
  168.  *  Get a new port structure
  169.  *    Allocate a signal for it
  170.  *    If none could be allocated
  171.  *      Free the structure
  172.  *    Otherwise
  173.  *      Set the port's name and type
  174.  *      Set its signal type and signal task
  175.  *      Add it to the port list if it has a name, otheriwse
  176.  *        initialize its message list
  177.  */
  178.  
  179. struct MsgPort *CreatePort(theName)
  180. char *theName;
  181. {
  182.    struct MsgPort *thePort;
  183.  
  184.    if (NEWSTRUCT(MsgPort,thePort))
  185.    {
  186.       thePort->mp_SigBit = AllocSignal(-ONE);
  187.       if (thePort->mp_SigBit == -ONE)
  188.       {
  189.          FREESTRUCT(MsgPort,thePort);
  190.          thePort = NULL;
  191.       } else {
  192.          thePort->mp_Node.ln_Name = theName;
  193.          thePort->mp_Node.ln_Type = NT_MESSAGE;
  194.          thePort->mp_Flags = PA_SIGNAL;
  195.          thePort->mp_SigTask = (struct Task *)FindTask(NULL);
  196.          if (theName) AddPort(thePort); else NewList(&(thePort->mp_MsgList));
  197.       }
  198.    }
  199.    return(thePort);
  200. }
  201.  
  202.  
  203. /*
  204.  *  DeletePort()
  205.  *
  206.  *  If the port exists
  207.  *    If it has a name, remove it frlom the system port list
  208.  *    Remove its type and message list
  209.  *    Free the port's signal
  210.  *    Free the ports memory
  211.  */
  212.  
  213. void DeletePort(thePort)
  214. struct MsgPort *thePort;
  215. {
  216.    if (thePort)
  217.    {
  218.       if (thePort->mp_Node.ln_Name) RemPort(thePort);
  219.       thePort->mp_Node.ln_Type = 0xFF;
  220.       thePort->mp_MsgList.lh_Head = (struct Node *)-1L;
  221.       FreeSignal(thePort->mp_SigBit);
  222.       FREESTRUCT(MsgPort,thePort);
  223.    }
  224. }
  225.  
  226.  
  227. /*
  228.  *  ReportEvent()
  229.  *
  230.  *  If the icon has an IconPort to send messages to
  231.  *    Get a new message structure
  232.  *    Increment the number of messages yet to be replied
  233.  *    Set the message's Window, Icon, Action and Flags fields
  234.  *    Set up the data field for special cases
  235.  *    Set the reply port to the IconPort and send the message
  236.  */
  237.  
  238. void ReportEvent(theEvent,theIcon,theData)
  239. ULONG theEvent;
  240. WICONREF *theIcon;
  241. APTR theData;
  242. {
  243.    struct wIconMessage *theMessage;
  244.  
  245.    if (theIcon->Icon.IconPort)
  246.    {
  247.       if (NEWSTRUCT(wIconMessage,theMessage))
  248.       {
  249.          MessageCount++;
  250.          theMessage->Window = theIcon->Window;
  251.          theMessage->Icon   = theIcon;
  252.          theMessage->Action = theEvent;
  253.          theMessage->Flags  = WI_ICONMESSAGE| WI_REPORT| WI_NOREPLY;
  254.          switch(theEvent) 
  255.          {
  256.             case WI_REPORTACTIVATE:
  257.             case WI_REPORTINACTIVE:
  258.             case WI_REPORTNEWSCREEN:
  259.             case WI_REPORTSCREENCLOSE:
  260.             case WI_REPORTICONEND:
  261.                theMessage->Data.DataPtr = theData;
  262.                break;
  263.  
  264.             case WI_REPORTICONVERIFY:
  265.                theMessage->Flags &= ~WI_ICONMESSAGE;
  266.                break;
  267.  
  268.             case WI_REPORTMOVED:
  269.                theMessage->Data.Position.x = theIcon->Icon.x;
  270.                theMessage->Data.Position.y = theIcon->Icon.y;
  271.                break;
  272.          }
  273.          theMessage->Message.mn_ReplyPort = wIconPort;
  274.          theMessage->Message.mn_Length = sizeof(struct wIconMessage);
  275.          PutMsg(theIcon->Icon.IconPort,theMessage);
  276.       }
  277.    }
  278. }
  279.  
  280.  
  281. /*
  282.  *  ReportMulti()
  283.  *
  284.  *  If a screen was specified, use it, otherwise start at the top of the list
  285.  *  While there are more screens to check
  286.  *    For each icon on the screen
  287.  *      If the icon wants to hear about this type of event, report it
  288.  *    If a screen was specified, we're done, otherwise go on to the next one
  289.  */
  290.  
  291. void ReportMulti(theEvent,theData,IconScreen)
  292. ULONG theEvent;
  293. APTR theData;
  294. WSCREEN *IconScreen;
  295. {
  296.    WSCREEN *theScreen;
  297.    WICONREF *theIcon,*nextIcon;
  298.    
  299.    Forbid();
  300.    if (IconScreen) theScreen = IconScreen; else theScreen = FirstScreen;
  301.    while (theScreen)
  302.    {
  303.       theIcon = theScreen->IconRef;
  304.       while (theIcon)
  305.       {
  306.          nextIcon = theIcon->Next;
  307.          if (theIcon->Icon.Report & theEvent)
  308.             ReportEvent(theEvent,theIcon,theData);
  309.          theIcon = nextIcon;
  310.       }
  311.       if (IconScreen) theScreen = NULL; else theScreen = theScreen->Next;
  312.    }
  313.    Permit();
  314. }
  315.  
  316.  
  317. /*
  318.  *  wMain()
  319.  *
  320.  *  Set the Wait signal bits to CANCEL, close and the bits used by the ports
  321.  *  While there is more to do
  322.  *    Don't try to end wIconify yet
  323.  *    Wait for one of the signals we're interested in
  324.  *    While there are messages in the common wIconify window UserPort
  325.  *      If the message type is CLOSEWINDOW ro NEWSIZE (fake messages
  326.  *        sent to Intuition windows by wIconify), then just free the message
  327.  *      Otherwise
  328.  *        Make a copy of the message data and reply the original
  329.  *        Do the event, and record whether we are supposed to end wIconify
  330.  *    While ther are messages in the IconPort (from the handler or IconCalls)
  331.  *      If the message is not an IconMessage being returned to us
  332.  *        Do what the message wants, and record if we are supposed to end
  333.  *      If the message is not supposed to be replied (it came from us)
  334.  *        If the message is a REPORT message we generated, decrement the count
  335.  *        If we are trying to end and there are no more outstanding messages
  336.  *          that need to be returned, go ahead and try to end
  337.  *        Free the message
  338.  *      Otherwise reply to the message (it's from IconCalls)
  339.  *    If the last window on a screen was closed, update the menus
  340.  *    If the loader wants us to end, try to quit
  341.  *    Do any pending mouse moves (since we're about to Wait anyway)
  342.  *    Refresh the screens that need it
  343.  *    If we are supposed to end
  344.  *      Try to close all screens and windows
  345.  *        If all are closed, make sure there are no outstanding messages
  346.  *          that need to be replied first; if not, go ahead and quit
  347.  */
  348.  
  349. static void wMain()
  350. {
  351.    int NotDone = TRUE;
  352.    int EndItAll;
  353.    ULONG WaitSignal = CANCELSIGNAL| CloseSignal;
  354.    ULONG theSignal;
  355.    struct IntuiMessage *inMessage,tmpMessage;
  356.    struct wIconMessage *wiMessage;
  357.    extern struct Node *GetMsg();
  358.  
  359.    if (wUserPort) WaitSignal |= (ONE << wUserPort->mp_SigBit);
  360.    if (wIconPort) WaitSignal |= (ONE << wIconPort->mp_SigBit);
  361.    while (NotDone)
  362.    {
  363.       EndItAll = FALSE;
  364.       theSignal = Wait(WaitSignal | EndSignal);
  365.       while (inMessage = (struct IntuiMessage *)GetMsg(wUserPort))
  366.       {
  367.          if (inMessage->Class & FREECLASS)
  368.          {
  369.             FREESTRUCT(IntuiMessage,inMessage);
  370.          } else {
  371.             tmpMessage = *inMessage; ReplyMsg(inMessage);
  372.             EndItAll = DoEvent(&tmpMessage,EndItAll);
  373.          }
  374.       }
  375.       while (wiMessage = (struct wIconMessage *)GetMsg(wIconPort))
  376.       {
  377.          if ((wiMessage->Flags & WI_ICONMESSAGE) == 0)
  378.             EndItAll = DoIconEvent(wiMessage,EndItAll);
  379.          if (wiMessage->Flags & WI_NOREPLY)
  380.          {
  381.             if (wiMessage->Flags & WI_REPORT) MessageCount--;
  382.             if (EndSignal && MessageCount == 0) EndItAll = TRUE;
  383.             FREESTRUCT(wIconMessage,wiMessage);
  384.          } else {
  385.             ReplyMsg(wiMessage);
  386.          }
  387.       }
  388.       if (theSignal & CloseSignal) UpdateActiveMenu();
  389.       if (theSignal & EndSignal)   EndItAll = TRUE;
  390.       DoMouseMove();
  391.       RefreshScreens();
  392.  
  393.       if (EndItAll)
  394.          if (AttemptQuit())
  395.             if (MessageCount == 0) NotDone = FALSE;
  396.    }
  397. }
  398.  
  399.  
  400. /*
  401.  *  ReplyMessages()
  402.  *
  403.  *  While there are more IntuiMessages in the UserPort
  404.  *    If the message is to be freed, do so, otherwise reply to it
  405.  *  While there are more IconMessages in the IconPort
  406.  *    If the message is not to be replied, free it, otherwise reply to it
  407.  */
  408.  
  409. static void ReplyMessages()
  410. {
  411.    struct IntuiMessage *inMessage;
  412.    struct wIconMessage *wiMessage;
  413.    extern struct Node *GetMsg();
  414.  
  415.    while (inMessage = (struct IntuiMessage *)GetMsg(wUserPort))
  416.    {
  417.       if (inMessage->Class & FREECLASS) FREESTRUCT(IntuiMessage,inMessage);
  418.         else ReplyMsg(inMessage);
  419.    }
  420.    while (wiMessage = (struct wIconMessage *)GetMsg(wIconPort))
  421.    {
  422.       if (wiMessage->Flags & WI_NOREPLY) FREESTRUCT(wIconMessage,wiMessage);
  423.         else wiMessage->Icon = NULL, ReplyMsg(wiMessage);
  424.    }
  425. }
  426.  
  427.  
  428. /*
  429.  *  AttemptEnd()
  430.  *
  431.  *  This routine is called when an ENDICONIFY message arrives.
  432.  *  Return a pointer to the HandlerData for use by the loader
  433.  *  Get the loader's task pointer from the message data pointer
  434.  */
  435.  
  436. void AttemptEnd(theMessage)
  437. struct wIconMessage *theMessage;
  438. {
  439.    theMessage->Icon = (WICONREF *) &HandlerData;
  440.    HandlerData.ParentTask = theMessage->Data.DataPtr;
  441. }
  442.